using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;

namespace AvalonAdmin.BaseViewModel
{
    /// <summary>
    /// 基础数据视图模型
    /// </summary>
    /// <typeparam name="T">数据类型</typeparam>
    public abstract class BaseDataViewModel<T> : Base, IDataViewModel<T>
    {
        #region 字段
        private ObservableCollection<T>? _data;
        private T? _selectedModel;
        private bool _isLoading;
        #endregion

        #region 属性
        /// <summary>
        /// 数据集合
        /// </summary>
        public ObservableCollection<T>? Data
        {
            get => _data;
            set
            {
                if (SetProperty(ref _data, value))
                {
                    OnPropertyChanged(nameof(HasData));
                    OnDataChanged();
                }
            }
        }

        /// <summary>
        /// 选中的模型
        /// </summary>
        public T? SelectedModel
        {
            get => _selectedModel;
            set
            {
                if (SetProperty(ref _selectedModel, value))
                {
                    OnPropertyChanged(nameof(HasSelectedModel));
                    OnSelectedModelChanged();
                }
            }
        }

        /// <summary>
        /// 是否正在加载
        /// </summary>
        public bool IsLoading
        {
            get => _isLoading;
            set => SetProperty(ref _isLoading, value);
        }

        /// <summary>
        /// 是否有数据
        /// </summary>
        public bool HasData => Data?.Count > 0;

        /// <summary>
        /// 是否有选中的模型
        /// </summary>
        public bool HasSelectedModel => SelectedModel != null;
        #endregion

        #region 抽象方法
        /// <summary>
        /// 查询数据
        /// </summary>
        /// <returns></returns>
        public abstract Task QueryAsync();

        /// <summary>
        /// 重置查询条件
        /// </summary>
        public virtual void Reset()
        {
            SelectedModel = default;
            _ = Task.Run(async () => await QueryAsync());
        }
        #endregion

        #region 虚拟方法
        /// <summary>
        /// 数据改变时触发
        /// </summary>
        protected virtual void OnDataChanged() { }

        /// <summary>
        /// 选中模型改变时触发
        /// </summary>
        protected virtual void OnSelectedModelChanged() { }
        #endregion

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler? PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        protected bool SetProperty<TValue>(ref TValue field, TValue value, [CallerMemberName] string? propertyName = null)
        {
            if (Equals(field, value)) return false;
            field = value;
            OnPropertyChanged(propertyName);
            return true;
        }
        #endregion
    }
}